package top.rainbowecho.gateway.security.support;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.stereotype.Component;
import top.rainbowecho.common.util.ExceptionMessageContent;
import top.rainbowecho.gateway.mapper.UserConnectionMapper;
import top.rainbowecho.gateway.mapper.UsersMapper;
import top.rainbowecho.model.field.UsersField;
import top.rainbowecho.model.percona.UserConnection;
import top.rainbowecho.model.percona.Users;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * @author rainbow
 * @since 2019/12/25 17:31
 */
@Component
@Slf4j
public class GatewayUserDetailService implements UserDetailsService, SocialUserDetailsService {
    private UsersMapper usersMapper;

    private UserConnectionMapper userConnectionMapper;

    private PasswordEncoder passwordEncoder;

    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    @Resource
    public void setUserConnectionMapper(UserConnectionMapper userConnectionMapper) {
        this.userConnectionMapper = userConnectionMapper;
    }

    @Resource
    public void setUsersMapper(UsersMapper usersMapper) {
        this.usersMapper = usersMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info(username + " 准备进行表单验证");

        // 根据用户用户名和邮箱地址列，查询登录用户的邮箱地址
        QueryWrapper<Users> queryWrapper = new QueryWrapper<Users>().eq(UsersField.USER_NAME, username)
                .or()
                .eq(UsersField.EMAIL, username);
        Users users = usersMapper.selectOne(queryWrapper);
        if (users == null) {
            throw new UsernameNotFoundException(ExceptionMessageContent.USER_NOT_EXIST);
        }

        return new User(username, users.getPassword(), AuthorityUtils.NO_AUTHORITIES);
    }


    @Override
    public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
        QueryWrapper<Users> queryWrapper = new QueryWrapper<Users>().eq(UsersField.ID, userId);
        Users users = usersMapper.selectOne(queryWrapper);
        log.info("第三方登录，进行用户查询: " + users);
        if (users == null) {
            // 如果为空，说明是第一次使用第三方账号登录，根据第三方账号信息，插入进系统表，将插入的信息作为UserDetails
            log.info("第三方用户第一次登录，进行自动注册，用户的userId为：" + userId);

            UserConnection userConnection = userConnectionMapper.selectById(userId);
            String password = RandomUtil.randomString(10);
            String encodePassword = this.passwordEncoder.encode(password);
            users = new Users().setId(userId).setRegisterTime(LocalDateTime.now())
                    .setEnable(1)
                    .setUserName(userConnection.getDisplayName())
                    .setPassword(encodePassword);
            usersMapper.insert(users);
        }

        return new SocialUser(users.getUserName(), users.getPassword(), AuthorityUtils.NO_AUTHORITIES);
    }
}
